/**
 * WebSocket工具类
 * 提供WebSocket连接管理、消息发送、接收和重连机制
 */

// WebSocket配置接口
export interface WSConfig {
  url: string // WebSocket服务器地址
  maxReconnectAttempts?: number // 最大重连次数
  reconnectDelayBase?: number // 基础重连延迟(毫秒)
  onMessage?: (message: any) => void // 消息接收回调
  onConnect?: () => void // 连接成功回调
  onDisconnect?: () => void // 连接断开回调
  onError?: (error: Event) => void // 错误回调
}

// WebSocket状态类型定义
export type WSStatus = 'disconnected' | 'connecting' | 'connected'

// WebSocket管理器类
class WebSocketManager {
  private ws: WebSocket | null = null // WebSocket实例
  private status: WSStatus = 'disconnected' // 当前连接状态
  private reconnectTimer: number | null = null // 重连定时器
  private reconnectAttempts = 0 // 当前重连尝试次数
  private config: WSConfig // 配置信息
  private messageQueue: object[] = [] // 消息队列(连接断开时暂存)
  private eventListeners: Map<string, ((data: any) => void)[]> = new Map() // 事件监听器集合

  // 构造函数
  constructor(config: WSConfig) {
    this.config = {
      maxReconnectAttempts: 5, // 默认最大重连次数
      reconnectDelayBase: 1000, // 默认基础重连延迟
      ...config,
    }
  }

  /**
   * 初始化WebSocket连接
   */
  connect(): void {
    // 关闭已存在的连接
    if (this.ws && this.ws.readyState !== WebSocket.CLOSED) {
      this.ws.close()
    }

    this.status = 'connecting'
    try {
      this.ws = new WebSocket(this.config.url)

      // 连接成功处理
      this.ws.onopen = () => {
        this.status = 'connected'
        this.reconnectAttempts = 0
        this.flushMessageQueue()
        this.config.onConnect?.()
        this.emit('connect')
      }

      // 接收消息处理
      this.ws.onmessage = event => {
        try {
          const message: any = JSON.parse(event.data)
          this.config.onMessage?.(message)
          this.emit(message.cmd, message)
        } catch (error) {
          console.error('解析WebSocket消息失败:', error)
        }
      }

      // 连接关闭处理
      this.ws.onclose = () => {
        this.status = 'disconnected'
        this.config.onDisconnect?.()
        this.emit('disconnect')
        this.attemptReconnect()
      }

      // 连接错误处理
      this.ws.onerror = error => {
        this.status = 'disconnected'
        this.config.onError?.(error)
        this.emit('error', error)
      }
    } catch (error) {
      console.error('初始化WebSocket失败:', error)
      this.status = 'disconnected'
      this.attemptReconnect()
    }
  }

  /**
   * 发送WebSocket消息
   * @param {any} message 要发送的消息
   * @returns {boolean} 是否发送成功
   */
  send(message: object): boolean {
    // 已连接状态直接发送
    if (this.ws && this.ws.readyState === WebSocket.OPEN) {
      this.ws.send(JSON.stringify(message))
      return true
    } else {
      // 未连接状态加入队列
      this.messageQueue.push(message)
      console.warn('WebSocket未连接，消息已加入队列')
      return false
    }
  }

  /**
   * 关闭WebSocket连接
   */
  close(): void {
    // 清除重连定时器
    if (this.reconnectTimer) {
      clearTimeout(this.reconnectTimer)
      this.reconnectTimer = null
    }
    // 关闭WebSocket
    if (this.ws) {
      this.ws.close()
      this.ws = null
    }
    this.status = 'disconnected'
  }

  /**
   * 获取当前WebSocket状态
   * @returns {WSStatus} 当前状态
   */
  getStatus(): WSStatus {
    return this.status
  }

  /**
   * 尝试重连
   */
  private attemptReconnect(): void {
    // 检查是否达到最大重连次数
    if (
      this.config.maxReconnectAttempts !== undefined &&
      this.reconnectAttempts >= this.config.maxReconnectAttempts
    ) {
      console.error('达到最大重连次数，停止重连')
      return
    }

    // 清除之前的重连定时器
    if (this.reconnectTimer) {
      clearTimeout(this.reconnectTimer)
    }

    // 指数退避重连策略 - 延迟时间随尝试次数指数增长
    const delay =
      Math.pow(2, this.reconnectAttempts) *
      (this.config.reconnectDelayBase ?? 1000)
    this.reconnectAttempts++

    // 设置重连定时器
    this.reconnectTimer = window.setTimeout(() => {
      console.log(`尝试第${this.reconnectAttempts}次重连...`)
      this.connect()
    }, delay)
  }

  /**
   * 发送队列中的消息
   */
  private flushMessageQueue(): void {
    // 遍历发送队列中所有消息
    while (this.messageQueue.length > 0) {
      const message = this.messageQueue.shift()
      if (message) {
        this.send(message)
      }
    }
  }

  /**
   * 添加事件监听器
   * @param {string} event 事件名称
   * @param {Function} callback 回调函数
   */
  on(event: string, callback: (data: any) => void): void {

    console.log(event, 'ssss');
    if (!this.eventListeners.has(event)) {
      this.eventListeners.set(event, [])
    }
    this.eventListeners.get(event)?.push(callback)
  }

  /**
   * 移除事件监听器
   * @param {string} event 事件名称
   * @param {Function} callback 回调函数
   */
  off(event: string, callback?: (data: any) => void): void {
    if (!this.eventListeners.has(event)) {
      return
    }

    if (callback) {
      // 移除特定回调
      const listeners = this.eventListeners.get(event)
      if (listeners) {
        const index = listeners.indexOf(callback)
        if (index !== -1) {
          listeners.splice(index, 1)
        }
      }
    } else {
      // 移除所有该事件的监听器
      this.eventListeners.delete(event)
    }
  }

  /**
   * 触发事件
   * @param {string} event 事件名称
   * @param {any} data 事件数据
   */
  private emit(event: string, data?: any): void {
    const listeners = this.eventListeners.get(event)
    if (listeners) {
      // 遍历执行所有回调
      listeners.forEach(callback => {
        try {
          callback(data)
        } catch (error) {
          console.error(`事件${event}回调执行失败:`, error)
        }
      })
    }
  }
}

/**
 * 创建WebSocket实例
 * @param {WSConfig} config WebSocket配置
 * @returns {WebSocketManager} WebSocket管理器实例
 */
export const createWebSocket = (config: WSConfig): WebSocketManager => {
  return new WebSocketManager(config)
}
